package com.sakura.demo2.gateway.handler;

import com.sakura.demo.common.constant.MessageConstant;
import com.sakura.demo.common.error.ErrorType;
import com.sakura.demo2.gateway.utils.WebfluxResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
import reactor.core.publisher.Mono;

/**
 * @Author: zhengcan
 * @Date: 2022/5/17
 * @Description: 网关异常通用处理器
 *                  只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
 * @Version: 1.0.0 创建
 */
@Slf4j
@Component
@Order(-1)
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        log.error("全局异常捕获，e={}", ex);
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        if (ex instanceof InvalidTokenException) {
            return WebfluxResponseUtil.responseFailed(exchange, HttpStatus.UNAUTHORIZED.value(), MessageConstant.INVALID_TOKEN);
        }
        return WebfluxResponseUtil.responseFailed(exchange, response.getStatusCode().value(), new ErrorType() {
            @Override
            public Integer getCode() {
                return response.getRawStatusCode();
            }

            @Override
            public String getMessage() {
                return ex.getMessage();
            }
        });
    }
}
